package com.zheng.redpacket.server.serivce.Impl;

import com.zheng.redpacket.mdg.mapper.PraiseMapper;
import com.zheng.redpacket.mdg.model.Praise;
import com.zheng.redpacket.mdg.model.PraiseRankDto;
import com.zheng.redpacket.server.dto.PraiseDto;
import com.zheng.redpacket.server.serivce.PraiseService;
import com.zheng.redpacket.server.serivce.RedisPraiseService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class PraiseServiceImpl implements PraiseService {
    private static final Logger LOGGER = LoggerFactory.getLogger(PraiseService.class);
    private static final String KEY_PREFIX_ADD = "PraiseAddLock";

    @Autowired
    private Environment env;
    @Autowired
    private PraiseMapper praiseMapper;
    @Autowired
    private RedissonClient redisson;
    @Autowired
    private RedisPraiseService redisPraiseService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPraise(PraiseDto dto) throws Exception {
        final String lockKey = KEY_PREFIX_ADD + ":" + dto.getBlogId() + ":" + dto.getUserId();
        //获取锁对象
        RLock lock = redisson.getLock(lockKey);
        lock.lock(1000L, TimeUnit.SECONDS);
        try {
            //查询是否已经点过赞
            Praise praise = praiseMapper.selectByBlogUserId(dto.getBlogId(), dto.getUserId());
            if (praise == null) {
                praise = new Praise();
                BeanUtils.copyProperties(dto, praise);
                praise.setPraiseTime(new Date());
                praise.setCreateTime(new Date());
                //将status字段设置为1，代表已点赞
                praise.setStatus(1);
                int res = praiseMapper.insertSelective(praise);
                if (res > 0) {
                    LOGGER.info("用户{}-点赞{}博客成功", dto.getUserId(), dto.getBlogId());
                    redisPraiseService.cachePraiseBlog(dto.getBlogId(), dto.getUserId(), 1);
                    //触发更新缓存中的排行榜
                    this.cachePraiseTotal();
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelPraise(PraiseDto dto) throws Exception {
        if (dto.getBlogId() != null && dto.getUserId() != null) {
            int result = praiseMapper.cancelPraiseBlog(dto.getBlogId(), dto.getUserId());
            if (result > 0) {
                LOGGER.info("取消点赞博客{}", dto.getBlogId());
                redisPraiseService.cachePraiseBlog(dto.getBlogId(), dto.getUserId(), 0);
                //触发更新缓存中的排行榜
                this.cachePraiseTotal();
            }
        }
    }

    @Override
    public Long getBlogPraiseTotal(Integer blogId) throws Exception {
        return redisPraiseService.getCacheTotalBlog(blogId);
    }

    @Override
    public Collection<PraiseRankDto> getRank() throws Exception {
        return redisPraiseService.getBlogPraiseRank();
    }

    /**
     * 将当前博客id对应的点赞总数构造为实体，并添加进RList中，构造排行榜
     * 记录当前博客id和点赞总数，构造实体排行榜
     */
    private void cachePraiseTotal(){
        try {
            redisPraiseService.rankBlogPraise();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
